package com.wispx.gateway.core.filter.loadblance;

import cn.hutool.json.JSONUtil;
import com.wispx.gateway.config.manager.DynamicConfigManager;
import com.wispx.gateway.config.pojo.RouteDefinition;
import com.wispx.gateway.config.pojo.ServiceInstance;
import com.wispx.gateway.config.util.FilterConfigUtil;
import com.wispx.gateway.core.context.GatewayContext;
import com.wispx.gateway.core.filter.Filter;
import com.wispx.gateway.core.filter.loadblance.strategy.LoadBalanceStrategy;

import java.util.List;
import java.util.Optional;

import static com.wispx.gateway.common.constant.FilterConstant.LOAD_BALANCE_FILTER_NAME;
import static com.wispx.gateway.common.constant.FilterConstant.LOAD_BALANCE_FILTER_ORDER;

public class LoadBalanceFilter implements Filter {

    @Override
    public void doPreFilter(GatewayContext ctx) {
        RouteDefinition.FilterConfig filterConfig = FilterConfigUtil.findFilterConfigByName(ctx.getRouteDefinition().getFilterConfigs(), LOAD_BALANCE_FILTER_NAME);
        filterConfig = Optional.ofNullable(filterConfig).orElse(FilterConfigUtil.buildDefaultLoadBalanceFilterConfig());
        if (!filterConfig.isEnable()) {
            ctx.doFilter();
            return;
        }
        List<ServiceInstance> instances = DynamicConfigManager.getInstance()
                .getServiceInstanceByServiceName(ctx.getRequest().getServiceDefinition().getServiceName())
                .values().stream().toList();
        LoadBalanceStrategy strategy = selectLoadBalanceStrategy(JSONUtil.toBean(filterConfig.getConfig(), RouteDefinition.LoadBalanceFilterConfig.class));
        ServiceInstance serviceInstance = strategy.selectInstance(ctx, instances);
        ctx.getRequest().setModifyHost(serviceInstance.getIp() + ":" + serviceInstance.getPort());
        ctx.doFilter();
    }

    @Override
    public void doPostFilter(GatewayContext ctx) {
        ctx.doFilter();
    }

    @Override
    public String mark() {
        return LOAD_BALANCE_FILTER_NAME;
    }

    @Override
    public int getOrder() {
        return LOAD_BALANCE_FILTER_ORDER;
    }

    private LoadBalanceStrategy selectLoadBalanceStrategy(RouteDefinition.LoadBalanceFilterConfig config) {
        return LoadBalanceStrategyManager.getLoadBalanceStrategy(config.getStrategyName());
    }

}
